<style lang="scss" scoped>
$border-color: #efefef;

.CalendarCss {
  position: relative;
  min-height: 200px;
  margin: 5px 15px;
  font-size: 14px;
  border: 1px solid $border-color;
  background: #fff;

  .cCurrentInfo {
    display: flex;
    align-items: center;
    > div,
    > view {
      display: flex;
      align-items: center;
    }
    .cLeft {
      padding: 5px;
      .ccDobule {
        display: flex;
        margin-right: 15px;
        > div:last-child,
        > view:first-child {
          margin-left: -5px;
        }
      }
    }

    .cRight {
      padding: 5px;
      .ccDobule {
        display: flex;
        margin-left: 15px;

        > div:first-child,
        > view:first-child {
          margin-right: -5px;
        }
      }
    }

    .cTime {
      flex: 1;
      justify-content: center;
      position: relative;

      span {
        font-size: 16px;
        font-weight: 600;
      }

      > div,
      > view {
        position: absolute;
        right: 0px;
      }
    }
    padding: 5px;
    border-bottom: 1px solid $border-color;
  }
  .cCenter {
    .cHeader {
      display: flex;
      border-bottom: 1px solid #fff;

      > div,
      > view {
        padding: 5px 8px;
        flex: 1;
        text-align: center;
        border-right: 1px solid #fff;
      }

      > div:last-child,
      > view:last-child {
        border-right: none;
      }
    }

    .cCollection {
      .week {
        display: flex;
        justify-content: space-between;
        border-bottom: 1px solid $border-color;
        .day {
          flex: 1;
          text-align: center;

          border-right: 1px solid $border-color;
          > div,
          > view {
            padding: 8px;
          }

          &.isCurrentDate {
            background: #f0f0f0 !important;
          }

          &.select {
            background: #7c8eeb !important;
            color: #fff;
            font-weight: 600;
          }

          &.currentMonth {
            background: #fffff0;
          }
        }

        > div:last-child,
        > view:last-child {
          border-right: none;
        }
      }

      > div:last-child,
      > view:last-child {
        border-bottom: none;
      }
    }
  }
}
</style>

<template>
  <div class="CalendarCss">
    <div class="cCurrentInfo">
      <div class="cLeft">
        <div class="ccDobule" @click="handlerChangeYear(-1)">
          <obIcon iconType="iconArrowLeft" />
          <obIcon iconType="iconArrowLeft" />
        </div>
        <obIcon iconType="iconArrowLeft" @onClick="handlerChangeMonth(-1)" />
      </div>
      <div class="cTime">
        <span>{{currentDateCn}}</span>
        <div @click="handlerReset">{{__LANG__('p.sign.date')}}</div>
      </div>
      <div class="cRight">
        <obIcon iconType="iconArrowRight" @onClick="handlerChangeMonth(1)" />
        <div class="ccDobule" @click="handlerChangeYear(1)">
          <obIcon iconType="iconArrowRight" />
          <obIcon iconType="iconArrowRight" />
        </div>
      </div>
    </div>
    <div class="cCenter">
      <div class="cHeader">
        <div v-for="(item,index) in headerData" :key="index">{{item}}</div>
      </div>
      <div class="cCollection">
        <div class="week" v-for="(week ,index) in dayCollection" :key="index">
          <div class="day" v-for="(day,dIndex) in week" :key="dIndex" :class="[{currentMonth: day.isCurrent },{select:day.isSelect},{isCurrentDate:day.isCurrentDate }]">
            <div @click="handlerSelectDay(day)">{{day.value}}</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Utility from '../../Utils/Utility';

class Calendar {
  props = {
    date: { type: Date, default: () => new Date() },
    dayItem: { type: Object, default: () => ({}) }
  };

  data = function() {
    return {
      currentDate: new Date(),
      currentDateCn: '',
      originDate: new Date(),
      headerData: ['日', '一', '二', '三', '四', '五', '六'],
      dayMap: {},
      dayCollection: [],
      counter: 1
    };
  };

  created = function() {
    //
    const { date } = this.$props;
    this.currentDate = new Date(date.getTime());
    this.originDate = date;

    this.initDayData(this.currentDate);
  };
  methods = {
    /**********************************************
     * 计算润年
     **********************************************/
    runNian(_year) {
      if (_year % 400 === 0 || (_year % 4 === 0 && _year % 100 !== 0)) {
        return true;
      } else {
        return false;
      }
    },
    /**********************************************
     * 获取第一天，在这个月里是星期几。
     **********************************************/
    getFirstDay(_year, _month) {
      let allDay = 0;
      const y = _year - 1;
      allDay = y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) + 1;
      for (let i = 1; i < _month; i++) {
        switch (i) {
          case 1:
            allDay += 31;
            break;
          case 2:
            // if (runNian(_year)) {
            allDay += this.runNian(_year) ? 29 : 28;
            // } else {
            //   allDay += 28;
            // }
            break;
          case 3:
            allDay += 31;
            break;
          case 4:
            allDay += 30;
            break;
          case 5:
            allDay += 31;
            break;
          case 6:
            allDay += 30;
            break;
          case 7:
            allDay += 31;
            break;
          case 8:
            allDay += 31;
            break;
          case 9:
            allDay += 30;
            break;
          case 10:
            allDay += 31;
            break;
          case 11:
            allDay += 30;
            break;
          case 12:
            allDay += 31;
            break;
        }
      }
      return allDay % 7;
    },
    /**********************************************
     * 初始化日期数据
     **********************************************/
    initDayData(now) {
      this.currentDateCn = Utility.$formatDate(this.currentDate, 'yyyy-MM-dd');
      const day = this.currentDate.getDate();

      for (let i = 0; i < 6; i += 1) {
        this.dayMap[i] = [];
      }

      const fDay = this.getFirstDay(now.getFullYear(), now.getMonth() + 1);
      const lastMonthDate = this.getLastMonthDate(now); // 获取上个月最好一天是多少号。
      const nextMonth = new Date(now);
      nextMonth.setMonth(now.getMonth() + 1);
      const nextMonthDate = this.getLastMonthDate(nextMonth);

      let beginNum = 1;
      let isCurrent = true;
      let isNextMonth = false;
      const yearMonth = Utility.$formatDate(now, 'yyyy-MM'); // 年月

      const initArrayData = (arr, index) => {
        for (let i = 0; i < 7; i += 1) {
          if (index === 0 && fDay !== 0 && i < fDay) {
            arr[i] = { isSelect: false, value: lastMonthDate - fDay + i + 1, isCurrent: false, isLast: true };
            // 获取上一个月。

            const lastMonth = new Date(now);
            lastMonth.setMonth(now.getMonth() - 1);
            lastMonth.setDate(arr[i].value);
            arr[i].yearMonthDay = Utility.$formatDate(lastMonth, 'yyyy-MM-dd');
          } else {
            arr[i] = { isSelect: false, value: beginNum, isCurrent };
            if (beginNum < nextMonthDate) {
              beginNum++;
              const currentMonth = new Date(now);
              currentMonth.setDate(beginNum - 1);
              arr[i].yearMonthDay = Utility.$formatDate(currentMonth, 'yyyy-MM-dd');
            } else {
              isCurrent = false;
              beginNum = 1;
              isNextMonth = true;
            }
          }

          if (isNextMonth === true) {
            const tmpNextMonth = new Date(nextMonth);
            tmpNextMonth.setDate(beginNum - 1);
            arr[i].yearMonthDay = Utility.$formatDate(tmpNextMonth, 'yyyy-MM-dd');
          }

          arr[i].isCurrentDate = isCurrent && day === arr[i].value;
          this.JudgeIsSelect(arr[i], now);
        }
      };

      Object.keys(this.dayMap).forEach(key => {
        initArrayData(this.dayMap[key], Number(key));
      });

      this.dayCollection = Object.values(this.dayMap);
    },

    /**********************************************
     * 判断是否选中
     **********************************************/
    JudgeIsSelect(opt, now) {
      const { dayItem } = this;
      const { yearMonthDay } = opt;
      if (dayItem[yearMonthDay]) {
        opt.isSelect = true;
      }
    },

    /**********************************************
     * 根据当前时间，计算出上个月的最后一天
     **********************************************/
    getLastMonthDate(now) {
      // 获取上个月最好一天是多少号。
      const tmpNow = new Date(now);
      tmpNow.setDate(0);
      const lastMonthDate = tmpNow.getDate();
      return lastMonthDate;
    },
    /**********************************************
     * 月更新
     **********************************************/
    handlerChangeMonth(value) {
      const cMonth = this.currentDate.getMonth();
      this.currentDate.setMonth(cMonth + value);
      this.initDayData(this.currentDate);

      this.$emit('onChangeDate', this.currentDate);
    },
    /**********************************************
     * 年更新
     **********************************************/
    handlerChangeYear(value) {
      const cYear = this.currentDate.getFullYear();
      this.currentDate.setFullYear(cYear + value);
      this.initDayData(this.currentDate);

      this.$emit('onChangeDate', this.currentDate);
    },
    /**********************************************
     * 选择日期
     **********************************************/
    handlerSelectDay(options) {
      const { isLast, isCurrent } = options;
      const nDate = new Date(this.currentDate.getTime());
      nDate.setDate(options.value);

      if (isLast) {
        nDate.setMonth(nDate.getMonth() - 1);
        this.handlerChangeMonth(-1);
      } else if (!isLast && !isCurrent) {
        nDate.setMonth(nDate.getMonth() + 1);
        this.handlerChangeMonth(1);
      } else {
        // Object.values(this.dayMap).forEach(row => {
        //   row.forEach(item => {
        //     item.isSelect = false;
        //   });
        // });
        // options.isSelect = true;
        this.dayCollection = Object.values(this.dayMap);
      }

      this.$emit('onClick', nDate);
    },
    /**********************************************
     * 重置
     **********************************************/
    handlerReset() {
      this.currentDate = new Date(this.originDate.getTime());
      this.initDayData(this.currentDate);
    }
  };

  watch = {
    dayItem(nValue, oValue) {
      this.dayItem = nValue;
    }
  };
}
export default { ...new Calendar(),  };
</script>